package com.bootdo.common.utils.orm;


import com.bootdo.common.utils.StringUtils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

/**
 * User: Allard
 * Date: 2017/3/31
 * Time: 13:51
 * Email: allards@synnex.com
 */
public class SqlNamedParamAppendUtil extends HashSet<String> {


    private Map<String, Object> params = new HashMap<String, Object>();
    private String[] orderbys;
    StringBuffer sqlBuffer = new StringBuffer();

    public SqlNamedParamAppendUtil() {
    }

    public SqlNamedParamAppendUtil(String sql) {
        sqlBuffer.append(sql);
    }

    public SqlNamedParamAppendUtil(String sql, String[] orderbys) {
        sqlBuffer.append(sql);
        this.orderbys = orderbys;
    }


    public SqlNamedParamAppendUtil setOrderbys(String... orderbys) {
        this.orderbys = orderbys;
        return this;
    }

    public SqlNamedParamAppendUtil add(String sql, Object param, boolean islike) {
        if (null != param) {
            if (param instanceof String) {
                if (!StringUtils.isEmpty(param.toString())) {
                    this.add(sql);
                    String paramName = getParamName(sql);
                    if (islike) {
                        params.put(paramName, "%" + ((String) param).trim().toUpperCase() + "%");
                    } else {
                        params.put(paramName, ((String) param).trim());
                    }
                }
            }else {
                this.add(sql);
                String paramName = getParamName(sql);
                params.put(paramName, param);
            }
        }
        return this;
    }
    public SqlNamedParamAppendUtil add(String sql, Object param) {
        if (null != param) {
            if (param instanceof String) {
                if (!StringUtils.isEmpty(param.toString())) {
                     this.add(sql);
                     String paramName = getParamName(sql);
                     params.put(paramName, ((String) param).trim());
                }
            }else {
                this.add(sql);
                String paramName = getParamName(sql);
                params.put(paramName, param);
            }
        }
        return this;
    }


    public String join() {
        StringBuffer resultSql = new StringBuffer(sqlBuffer);
        Iterator<String> iterator = this.iterator();
        while (iterator.hasNext()) {
            resultSql.append(" " + iterator.next());
        }
        if (orderbys != null && orderbys.length > 0) {
            Integer orderBysLength = orderbys.length;
            resultSql.append(" ORDER  BY ");
            for (int i = 0; i < orderBysLength; i++) {
                if (i == orderBysLength - 1) {
                    resultSql.append(" " + orderbys[i]);
                } else {
                    resultSql.append(" " + orderbys[i] + " , ");
                }
            }
        }

        return resultSql.toString();
    }


    public Map<String, Object> getParams() {
        return params;
    }


    public String getParamName(String sql) {
        boolean flag = sql.contains(":");
        if (flag) {
            int index = sql.indexOf(":");
            int end = 0;
            String[] inParams = sql.split(":");
            String subInParam = inParams[1];
            if (subInParam.contains(")")) {
                int x1 = subInParam.indexOf(")");
                if (x1 == 0) {
                    throw new RuntimeException("sql error");
                }

                if (subInParam.contains(" ")) {
                    int x2 = subInParam.indexOf(" ");
                    if (x2 == 0) {
                        throw new RuntimeException("sql error");
                    }
                    if (x1 < x2) {
                        end = x1;
                    } else {
                        end = x2;
                    }
                }
                end = x1;
            } else {
                int x3 = subInParam.indexOf(" ");
                if (x3 == 0) {
                    throw new RuntimeException("sql error");
                } else if (x3 == -1) {
                    end = subInParam.length();
                } else {
                    end = x3;
                }

            }
            return sql.substring(index + 1, index + end + 1);
        } else {
            throw new RuntimeException("paramName not found");
        }
    }


    public Integer getParamSize() {
        return params.size();
    }

    public static void main(String[] args) {
        String sql1 = "and name in (:name) ";
        String param1 = "xiaohaong,xiaoming,xiaobai";

        String sql2 = "and old = :old ";
        Integer old = 25;


        String sql3 = "and dep like :hr";
        String hr = "hr1";


        String sql4 = "and sex = :sex ";
        Integer sex = null;


        SqlNamedParamAppendUtil sqlNamedParamSetUtil = new SqlNamedParamAppendUtil("select * from table where 1=1 ");
        sqlNamedParamSetUtil.add(sql1, param1).add(sql2, old).add(sql3, hr,true).add(sql4, sex).setOrderbys(" name asce ", "old asc ");
        System.out.println(sqlNamedParamSetUtil.join());

        System.out.println(sqlNamedParamSetUtil.getParams());

    }
}
